package com.quanyan.user.service.impl;


import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.AssetsPayReceive;
import com.quanyan.api.enums.AssetsType;
import com.quanyan.assets.request.ReqUserAccumulateModify;
import com.quanyan.assets.response.RespUserAccumulateModify;
import com.quanyan.assets.service.UserAssetsService;
import com.quanyan.comment.enums.TaskEnum;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.redisCluster.utils.SerializeUtil;
import com.quanyan.user.cache.MyRedisTemplate;
import com.quanyan.user.constants.UserConstants;
import com.quanyan.user.mapper.*;
import com.quanyan.user.model.db.*;
import com.quanyan.user.model.vo.request.ReqUserLevel;
import com.quanyan.user.model.vo.response.RespReceiveDetail;
import com.quanyan.user.model.vo.response.RespUserTask;
import com.quanyan.user.model.vo.response.RespUserTreasureBox;
import com.quanyan.user.request.ReqReceiveEggShell;
import com.quanyan.user.service.ReceiveDetailService;
import com.quanyan.user.service.UserLevelService;
import com.quanyan.user.service.UserQueryService;
import com.quanyan.user.service.UserTreasureBoxService;
import com.quanyan.user.utils.ValidUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by jian.zhou on 2016/6/30.
 * 领取明细
 */
@Service
public class ReceiveDetailServiceImpl implements ReceiveDetailService {
    private static final Logger logger = LoggerFactory.getLogger(ReceiveDetailService.class);

    @Autowired
    private TbReceiveDetailMapper tbReceiveDetailMapper;

    @Autowired
    private TbUserTaskMapper tbUserTaskMapper;

    @Autowired
    private TbTaskMapper tbTaskMapper;

    @Autowired
    private ReceiveDetailMapper receiveDetailMapper;

    @Autowired
    private TbUserTreasureBoxMapper tbUserTreasureBoxMapper;

    @Autowired
    private MyRedisTemplate myRedisTemplate;

    @Autowired
    private UserAssetsService userAssetsService;

    @Autowired
    private UserQueryService userQueryService;


    @Autowired
    private UserLevelService userLevelService;

    @Autowired
    private UserTreasureBoxService userTreasureBoxService;


    @Override
    public  List<RespReceiveDetail>  queryReceiveDetail(Integer uid) {
        logger.info("star queryReceiveDetail uid:{} ",uid);
        List<RespReceiveDetail> respReceiveDetailsList = new ArrayList<RespReceiveDetail>();

        List<TbReceiveDetail> tbReceiveDetailList = receiveDetailMapper.findByDay(uid);
        if(tbReceiveDetailList == null || tbReceiveDetailList.size() < 1)
            return respReceiveDetailsList;
        for (TbReceiveDetail tbReceiveDetail : tbReceiveDetailList){
            if(tbReceiveDetail.getType().intValue() == UserConstants.NEW_HAND_TASK
                    && tbReceiveDetail.getTaskBoxId().intValue() == TaskEnum.TASK_ENUM__MOBILE.getId())
            continue;

            RespReceiveDetail respReceiveDetail = new RespReceiveDetail();
            respReceiveDetail.setId(tbReceiveDetail.getId());
            respReceiveDetail.setReceiveEggShellNum(new BigDecimal(tbReceiveDetail.getEggshellNum()));
            respReceiveDetail.setTaskOrBoxId(tbReceiveDetail.getTaskBoxId());
            respReceiveDetail.setName(tbReceiveDetail.getName());
            respReceiveDetail.setType(tbReceiveDetail.getType());
            respReceiveDetail.setReceiveDate(tbReceiveDetail.getCreateTime().getTime());
            respReceiveDetailsList.add(respReceiveDetail);
        }
        logger.info("end queryReceiveDetail result");
        return respReceiveDetailsList;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void addReceiveDetail(ReqReceiveEggShell reqReceiveEggShell) {
        int uid = reqReceiveEggShell.getUid();
        String uidTaskDayKey = UserConstants.getUserTaskRedisKey(uid);//uid
        ValidUtils<ReqReceiveEggShell> validUtils = new ValidUtils<>();
        List<String> lstErrorMsg = validUtils.getListMessage(reqReceiveEggShell);
        if(lstErrorMsg != null && lstErrorMsg.size() > 0)
            return ;
        logger.info("star add receive detail param is :{}",reqReceiveEggShell.toString());
        TbUser tbUser = userQueryService.getUser(uid);
        if(tbUser == null){
            logger.info("用户ID为：【{}】的用户不存在！领取失败",uid);
            return;
        }

        if(reqReceiveEggShell.getReceiveType().intValue() == UserConstants.ReceiveType.BOX.intValue()){ //增加 领取宝箱奖励 明细
            logger.info("开始增加宝箱领取明细------------------------------------------------------");
            TbTreasureBox tbTreasureBox = (TbTreasureBox)myRedisTemplate.hget(UserConstants.UC_SYS_BOX,reqReceiveEggShell.getTaskOrBoxId().toString());
            RespUserTreasureBox respUserTreasureBox =(RespUserTreasureBox) myRedisTemplate.hget(UserConstants.getUserBoxRedisKey(uid),reqReceiveEggShell.getTaskOrBoxId().toString());
            logger.info("uid:{}用户宝箱result:{}:------------------------------------------------------",uid,respUserTreasureBox.toString());
            if(UserConstants.BoxStatus.OPEN_NO_RECEIVE == respUserTreasureBox.getStatus()){ // 用户宝箱为待领取状态
                logger.info("开始增加领取宝箱奖励明细------------------");
                TbReceiveDetail tbReceiveDetail = new TbReceiveDetail();
                tbReceiveDetail.setUid(uid);
                tbReceiveDetail.setEggshellNum(tbTreasureBox.getReward());
                tbReceiveDetail.setTaskBoxId(reqReceiveEggShell.getTaskOrBoxId());
                tbReceiveDetail.setType(UserConstants.ReceiveType.BOX);
                tbReceiveDetail.setName(tbTreasureBox.getName());
                tbReceiveDetail.setCreateTime(new Date());
                tbReceiveDetail.setUpdateTime(new Date());
                tbReceiveDetail.setIsDelete(Constants.IS_DELETE_FALSE);
                int result = receiveDetailMapper.insertDuplicate(tbReceiveDetail);
                if(result == UserConstants.duplicate_insert){
                    logger.info("开始调用资产系统------》");
                    //增加蛋壳
                    APIResponse<RespUserAccumulateModify> response = this.addEggShell(uid,tbTreasureBox.getCode(),tbReceiveDetail.getId());
                    if(!response.isRet()){
                        logger.error("增加蛋壳失败{}",response.getErrmsg());
                        throw new BizException(response.getErrmsg());
                    }
                    logger.info("开始更改用户宝箱的状态已领取{}------------------",UserConstants.BoxStatus.OPEN_YES_RECEIVE);
                    respUserTreasureBox.setStatus(UserConstants.BoxStatus.OPEN_YES_RECEIVE);//宝箱状态更改为已经领取
                    myRedisTemplate.hset(UserConstants.getUserBoxRedisKey(uid),reqReceiveEggShell.getTaskOrBoxId().toString(),respUserTreasureBox);
                    logger.info("结束更改用户宝箱的状态已领取{}------------------");
                }
                logger.info("结束增加领取宝箱奖励明细------------------");
            }
        } else { //领取任务奖励明细
            //增加领取明细
            logger.info("开始增加任务领取明细------------------------------------------------------");
            if(reqReceiveEggShell.getTaskOrBoxId().intValue() == TaskEnum.TASK_ENUM__T_EGG_SHELLS.getId()){
                logger.info("掏鸟蛋特殊任务不增加！");
                return;
            }
            TbTask tbTask = this.getTbTask(reqReceiveEggShell.getTaskOrBoxId());
            if(tbTask.getType().byteValue() == UserConstants.NEW_HAND_TASK){
                logger.info("开始领取新手任务------》");
                TbUserTaskExample tbUserTaskExample = new TbUserTaskExample();
                TbUserTaskExample.Criteria criteria = tbUserTaskExample.createCriteria();
                criteria.andUidEqualTo(uid);
                criteria.andTaskIdEqualTo(reqReceiveEggShell.getTaskOrBoxId());
                List<TbUserTask> lst = tbUserTaskMapper.selectByExample(tbUserTaskExample);
                if(lst == null || lst.size() < 1){
                    logger.info("用户新手任务不存在");
                    return;
                }
                TbUserTask tbUserTask = lst.get(0);
                logger.info("用户的新手任务{}",tbUserTask.toString());
                if(UserConstants.TaskStatus.RECEIVED == tbUserTask.getStatus().byteValue()){
                    logger.info("箱子已经领取过了");
                    return;
                }
                if(UserConstants.TaskStatus.COMPLETED == tbUserTask.getStatus().byteValue()){//状态为领取
                    this.addReceiveAndEgg(uid,tbTask);//增加领取明细，经验 ，蛋壳
                    tbUserTask.setStatus(UserConstants.TaskStatus.RECEIVED);
                    tbUserTask.setUpdateTime(new Date());
                    logger.info("开始更改领取状态");
                    tbUserTaskMapper.updateByPrimaryKeySelective(tbUserTask);
                    logger.info("结束更改领取状态");
                }

            }else  if(tbTask.getType().byteValue() == UserConstants.DAY_TASK){
                RespUserTask respUserTask = (RespUserTask)myRedisTemplate.hget(uidTaskDayKey, reqReceiveEggShell.getTaskOrBoxId().toString());
                if(respUserTask == null){
                    logger.info("该用户不存改任务");
                    return;
                }
                logger.info("领取的任务是：{}",respUserTask.toString());
                if(UserConstants.TaskStatus.COMPLETED == respUserTask.getStatus().byteValue()){//状态为领取 -->领取
                    this.addReceiveAndEgg(uid,tbTask);
                    //更改该用户任务状态
                    logger.info("开始更改用户任务状态为已领取------------------");
                    respUserTask.setStatus(UserConstants.TaskStatus.RECEIVED); //任务更改为已领取
                    myRedisTemplate.hset(uidTaskDayKey,respUserTask.getTaskId().toString(),respUserTask);
                    logger.info("结束更改用户任务状态为已领取------------------");

                    if(tbTask.getType().byteValue() == UserConstants.ReceiveType.DAY_TASK.byteValue()){//日常任务
                        logger.info("日常任务----》累积蛋壳，判断是否开开启宝箱-------------");
                        Long currentDayReceiveEggShellNum = this.getCurrentDayReceiveEggShellNum(uid);//当日 获得鸟蛋数量
                        logger.info("日常任务----》当日获得鸟蛋数量：{}-------------",currentDayReceiveEggShellNum);
                        String userBoxKey = UserConstants.getUserBoxRedisKey(uid);
                        Map<byte[],byte[]> map = myRedisTemplate.hgetAll(userBoxKey);
                        if(map == null || map.size() < 1){
                            userTreasureBoxService.setUpUserBox(uid);
                            map = myRedisTemplate.hgetAll(userBoxKey);
                        }
                        logger.info("宝箱数量：{}",map.size());
                        for (Map.Entry<byte[], byte[]> entry : map.entrySet()) {
                            RespUserTreasureBox userBox = (RespUserTreasureBox) SerializeUtil.unserialize(entry.getValue());//用户宝箱
                            if(userBox.getStatus() == UserConstants.BoxStatus.OPEN_FALSE){//未开启的宝箱
                                logger.info("用户未开启的宝箱：{}",userBox.toString());
                                if(currentDayReceiveEggShellNum >= userBox.getRuleEggShellsNum().longValue()){// 当前获得鸟蛋数量大与等于 鸟蛋数量
                                    logger.info("开始开启宝箱，更改宝箱状态----------------》{}",userBox.toString());
                                    userBox.setStatus(UserConstants.BoxStatus.OPEN_NO_RECEIVE);
                                    myRedisTemplate.hset(userBoxKey,userBox.getBoxId().toString(),userBox);//更改箱子状态
                                    logger.info("结束开启宝箱，更改宝箱状态----------------》{}",userBox.toString());

                                }
                            }
                        }
                    }

                }

            }

        }
        logger.info("end  add receive detail param is :{}");
    }


    public void addReceiveAndEgg(Integer uid,TbTask tbTask){
        logger.info("开始增加领取任务奖励明细------------------");
        TbReceiveDetail tbReceiveDetail = new TbReceiveDetail();
        tbReceiveDetail.setUid(uid);
        tbReceiveDetail.setEggshellNum(tbTask.getReward());
        tbReceiveDetail.setTaskBoxId(tbTask.getId());
        tbReceiveDetail.setType(tbTask.getType().intValue());
        tbReceiveDetail.setName(tbTask.getTaskName());
        tbReceiveDetail.setCreateTime(new Date());
        tbReceiveDetail.setUpdateTime(new Date());
        tbReceiveDetail.setIsDelete(Constants.IS_DELETE_FALSE);
        int result = receiveDetailMapper.insertDuplicate(tbReceiveDetail);
        if(result == UserConstants.duplicate_insert){
            logger.info("开始调用资产系统==========》");
            //增加蛋壳
            APIResponse<RespUserAccumulateModify> response = this.addEggShell(uid,tbTask.getCode(),tbReceiveDetail.getId());
            if(response.isRet()==false)
                throw new BizException(response.getErrmsg());
            //增加经验
            ReqUserLevel reqUserLevel = new ReqUserLevel();
            reqUserLevel.setUid(uid);
            reqUserLevel.setExperience(tbTask.getExperience());
            userLevelService.modifyExperience(reqUserLevel);
            logger.info("结束调用资产系统==========》");
        }
        logger.info("结束增加领取任务奖励明细------------------");

    }


    /**
     *  获取当日 获得鸟蛋数量
     * @param uid
     * @return
     */
    public Long  getCurrentDayReceiveEggShellNum(Integer uid){
        logger.info("开始获得用户：{}当日累积领取蛋壳数量-----------》",uid);
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("uid",uid);
        map.put("type",UserConstants.DAY_TASK);
        Long eggShells = receiveDetailMapper.getCurrentDayReceiveEggShellNum(map);
        if(eggShells == null)
            eggShells = 0L;
        logger.info("结束获得用户：当日累积领取蛋壳数量{}-----------》",eggShells);
        return eggShells;


    }

    /**
     * @param boxId
     *  从缓存中获取系统宝箱
     */
    public TbUserTreasureBox getTbUserTreasureBox(Integer boxId){
        if(boxId == null)
            return null;
        TbUserTreasureBox tbUserTreasureBox = (TbUserTreasureBox)myRedisTemplate.hget(UserConstants.UC_SYS_BOX,boxId.toString());
        if(tbUserTreasureBox != null)
            return tbUserTreasureBox;

        return tbUserTreasureBoxMapper.selectByPrimaryKey(boxId);
    }

    /**
     * 从缓存中获取系统任务
     * @param taskId
     * @return
     */
    public TbTask getTbTask(Integer taskId){
        if(taskId == null)
            return null;
        TbTask tbTask = (TbTask)myRedisTemplate.hget(UserConstants.UC_SYS_TASK,taskId.toString());
        if(tbTask != null)
            return tbTask;
        return tbTaskMapper.selectByPrimaryKey(taskId);
    }

    /**
     * 增加蛋壳
     */
    public APIResponse<RespUserAccumulateModify> addEggShell(Integer uid,String businessCode,Integer businessId){
        logger.info("开始增加蛋壳。。。。。。。。。。");
        APIRequest<ReqUserAccumulateModify> apiRequest = new APIRequest<ReqUserAccumulateModify>();
        ReqUserAccumulateModify r = new ReqUserAccumulateModify();
        r.setUid(uid);
        r.setSystemCode(Constants.USER_CENTER_SYSTEM_CODE);
        r.setBusinessCode(businessCode);
        r.setBusinessId(businessId);
        if(businessCode.equals(TaskEnum.TASK_ENUM__MOBILE.getCode())){
            logger.info("登录绑定手机号增加鸟蛋鸟蛋鸟蛋");
            r.setAssetsType(AssetsType.ASSETS_EGGS.getId().byteValue());
            r.setInfo("注册百灵鸟账号");
        }//登录 增加鸟蛋
        else{
            logger.info("增加蛋壳-----------------------》");
            r.setAssetsType(AssetsType.ASSETS_SHELL.getId().byteValue());//增加蛋壳
        }
        TbUser tbUser = userQueryService.getUser(uid);
        if(tbUser.getNickName() == null)
          r.setReceiver(tbUser.getNickName());
        else
          r.setReceiver(tbUser.getMobile());
        r.setPayReceive(AssetsPayReceive.SYSTEM.getName());
        apiRequest.setData(r);
        logger.info("增加鸟蛋的参数{}",r.toString());
        APIResponse<RespUserAccumulateModify> response = userAssetsService.modifyAccumulate(apiRequest);
        logger.info("调取接口完毕---------------------》");
        return response;
    }


    /**
     * 首次充值//增加蛋壳
     */
    public APIResponse<RespUserAccumulateModify> addEggShell(Integer uid,Integer businessId){
        logger.info("开始增加蛋壳。。。。。。。。。。");
        APIRequest<ReqUserAccumulateModify> apiRequest = new APIRequest<ReqUserAccumulateModify>();
        ReqUserAccumulateModify r = new ReqUserAccumulateModify();
        r.setUid(uid);
        r.setSystemCode(Constants.USER_CENTER_SYSTEM_CODE);
        r.setBusinessCode(Constants.USER_CENTER_SHELL_BY_EGGS_RECHANGE_CODE);
        r.setBusinessId(businessId);
        logger.info("增加蛋壳-----------------------》");
        r.setAssetsType(AssetsType.ASSETS_SHELL.getId().byteValue());//增加蛋壳
        r.setReceiver(userQueryService.getUser(uid).getNickName());
        r.setPayReceive(AssetsPayReceive.SYSTEM.getName());
        apiRequest.setData(r);
        logger.info("增加鸟蛋的参数{}",r.toString());
        APIResponse<RespUserAccumulateModify> response = userAssetsService.modifyAccumulate(apiRequest);
        logger.info("调取接口完毕---------------------》");
        return response;
    }


    /**
     * 设置当日奖励
     * @param uid
     * @param reward
     */
    public void setTodayReceive(Integer uid ,Long reward){
        String key = UserConstants.getReceiveRedisKey(uid);
        myRedisTemplate.set(key,reward);
        myRedisTemplate.setExpire(key,1);//一天失效
    }

    /**
     *
     * @param uid
     * @return
     */
    public Long getTodayReceiveShell(Integer uid){
        String key = UserConstants.getReceiveRedisKey(uid);
        Long receiveShell = (Long)myRedisTemplate.get(key);
        return receiveShell;
    }
}
